package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.binary.core.exception.BinaryException;
import com.uinnova.product.eam.comm.model.es.EamCategory;
import com.uinnova.product.eam.dto.*;
import com.uinnova.product.eam.model.cj.domain.TemplateType;
import com.uinnova.product.eam.model.enums.CategoryTypeEnum;
import com.uinnova.product.eam.service.AXEAConfService;
import com.uinnova.product.eam.service.asset.BmConfigSvc;
import com.uinnova.product.eam.service.cj.service.DeliverableTemplateService;
import com.uinnova.product.eam.service.es.EamCategoryDesignDao;
import com.uinnova.product.vmdb.comm.model.ci.CCcCiClass;
import com.uinnova.product.vmdb.provider.ci.bean.CcCiClassInfo;
import com.uino.service.cmdb.microservice.impl.CIClassSvc;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Log4j2
public class AXEAConfServiceImpl implements AXEAConfService {

    public static final String AXEA_CONFIG = "AXEA_CONFIG";
    @Autowired
    private BmConfigSvc bmConfigSvc;
    @Autowired
    private CIClassSvc ciClassSvc;
    @Autowired
    private EamCategoryDesignDao categoryDesignDao;
    @Autowired
    private DeliverableTemplateService deliverableTemplateService;

    @Override
    public AXEAConf getCategoryAutoConf() {
        String configJson = bmConfigSvc.getConfigType(AXEA_CONFIG);
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        AXEAConf conf = JSON.parseObject(configJson, AXEAConf.class);
        if (CollectionUtils.isEmpty(conf.getCategoryCreates())) {
            log.error("需要进行系统文件夹创建的分类配置为空");
            throw new BinaryException("需要进行系统文件夹创建的分类配置为空，请联系管理员");
        }
        List<CcCiClassInfo> classInfos = getClassInfos(conf.getCategoryCreates());
        if (CollectionUtils.isEmpty(classInfos) || conf.getCategoryCreates().size() != classInfos.size()) {
            log.error("需要进行系统文件夹创建的分类配置错误:classCodes:{}", conf.getCategoryCreates());
            throw new BinaryException("需要进行系统文件夹创建的分类配置错误");
        }
        if (CollectionUtils.isEmpty(conf.getClassConf())) {
            log.error("分类配置为空");
            throw new BinaryException("分类配置为空，请联系管理员");
        }
        Map<String, AXEAClassDetailConf> classConf = conf.getClassConf();
        for (String classCode : conf.getCategoryCreates()) {
            if (!classConf.containsKey(classCode)) {
                String msg = "需创建的系统文件夹分类".concat(classCode).concat("缺少分类配置");
                log.error(msg);
                throw new BinaryException(msg);
            }
            AXEAClassDetailConf classDetailConf = classConf.get(classCode);
            if (CollectionUtils.isEmpty(classDetailConf.getOwnerDefs())) {
                log.error("负责人属性字段不能为空");
                throw new BinaryException("负责人属性字段不能为空");
            }
            if (classDetailConf.getDesignRootId() == null) {
                log.error("分类系统文件夹归属资产仓库根目录id不能为空");
                throw new BinaryException("分类系统文件夹归属资产仓库根目录id不能为空");
            }
            EamCategory designRoot = getDesignRoot(classDetailConf.getDesignRootId());
            if (designRoot == null) {
                String msg = "未找到分类".concat(classCode).concat("的文件夹归属资产仓库根目录");
                log.error(msg);
                throw new BinaryException(msg);
            }
        }
        return conf;
    }

    private List<CcCiClassInfo> getClassInfos(List<String> classCodes) {
        CCcCiClass cdt = new CCcCiClass();
        cdt.setClassCodes(classCodes.toArray(new String[0]));
        return ciClassSvc.queryClassByCdt(cdt);
    }

    private EamCategory getDesignRoot(Long designRootId) {
        BoolQueryBuilder query = QueryBuilders.boolQuery();
        query.must(QueryBuilders.termQuery("type", CategoryTypeEnum.ROOT.val()));
        query.must(QueryBuilders.termQuery("dataStatus", 1));
        query.must(QueryBuilders.termQuery("id", designRootId));
        List<EamCategory> roots = categoryDesignDao.getListByQuery(query);
        return CollectionUtils.isEmpty(roots) ? null : roots.get(0);
    }

    @Override
    public AXEAClassMapping getSystemClassMapping() {
        String configJson = bmConfigSvc.getConfigType(AXEA_CONFIG);
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        AXEAConf conf = JSON.parseObject(configJson, AXEAConf.class);
        if (conf.getClassMapping() == null) {
            throw new BinaryException("未查询到国投分类映射配置，请联系管理员");
        }
        AXEAClassMapping axeaClassMapping = conf.getClassMapping();
        if (StringUtils.isBlank(axeaClassMapping.getSystemClassCode())) {
            throw new BinaryException("未查询到国投系统分类映射配置，请联系管理员");
        }
        List<CcCiClassInfo> ciClassInfos = getClassInfos(Arrays.asList(axeaClassMapping.getSystemClassCode()));
        if (CollectionUtils.isEmpty(ciClassInfos)) {
            String msg = "未查询到国投系统分类[systemClassCode:"
                    .concat(axeaClassMapping.getSystemClassCode()).concat("]，请联系管理员");
            throw new BinaryException(msg);
        }
        axeaClassMapping.setSystemClassId(ciClassInfos.get(0).getCiClass().getId());
        return axeaClassMapping;
    }

    @Override
    public ArchReviewConf getArchReviewConf() {
        String configJson = bmConfigSvc.getConfigType(AXEA_CONFIG);
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        AXEAConf conf = JSON.parseObject(configJson, AXEAConf.class);
        if (conf.getClassMapping() == null) {
            throw new BinaryException("未查询到国投分类映射配置，请联系管理员");
        }
        if (StringUtils.isBlank(conf.getArchReviewTemplateTypeName())) {
            throw new BinaryException("未查询到国投架构方案模板类型配置，请联系管理员");
        }
        TemplateType templateType = deliverableTemplateService.getTemplateTypeByName(conf.getArchReviewTemplateTypeName());
        if (templateType == null) {
            log.error("未查询到国投架构方案模板类型配置[archReviewTemplateTypeName:{}]，请联系管理员", conf.getArchReviewTemplateTypeName());
            throw new BinaryException("未查询到国投架构方案模板类型配置，请联系管理员");
        }
        AXEAClassMapping axeaClassMapping = conf.getClassMapping();
        if (StringUtils.isBlank(axeaClassMapping.getProjectClassCode())) {
            throw new BinaryException("未查询到国投项目分类映射配置，请联系管理员");
        }
        List<CcCiClassInfo> ciClassInfos = getClassInfos(Arrays.asList(axeaClassMapping.getProjectClassCode()));
        if (CollectionUtils.isEmpty(ciClassInfos)) {
            String msg = "未查询到国投项目分类[projectClassCode:"
                    .concat(axeaClassMapping.getProjectClassCode()).concat("]，请联系管理员");
            throw new BinaryException(msg);
        }
        if (CollectionUtils.isEmpty(conf.getArchReviewOrgIds())) {
            throw new BinaryException("未配置架构评审-团队组织路径，请联系管理员");
        }
        ArchReviewConf archReviewConf = new ArchReviewConf();
        archReviewConf.setProjectClassCode(axeaClassMapping.getProjectClassCode());
        archReviewConf.setProjectClassId(ciClassInfos.get(0).getCiClass().getId());
        archReviewConf.setArchReviewTemplateTypeName(templateType.getTypeName());
        archReviewConf.setArchReviewTemplateTypeId(templateType.getId());
        archReviewConf.setArchReviewOrgIds(conf.getArchReviewOrgIds());
        return archReviewConf;
    }

    @Override
    public IndicatorClassifyConf indicatorClassifyDictoryName() {
        String configJson = bmConfigSvc.getConfigType(AXEA_CONFIG);
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject config = JSON.parseObject(configJson);
        String indicatorClassifyDictoryName = config.getString("indicatorClassifyDictoryName");
        if (StringUtils.isBlank(indicatorClassifyDictoryName)) {
            throw new BinaryException("未配置指标分类数据字典名称，请联系管理员");
        }
        String indicatorClassifyAttrName = config.getString("indicatorClassifyAttrName");
        if (StringUtils.isBlank(indicatorClassifyDictoryName)) {
            throw new BinaryException("未配置指标分类数据字典属性名称，请联系管理员");
        }
        return new IndicatorClassifyConf(indicatorClassifyDictoryName, indicatorClassifyAttrName);
    }

    @Override
    public List<String> assertRangeClassCodes() {
        String configJson = bmConfigSvc.getConfigType(AXEA_CONFIG);
        if (StringUtils.isBlank(configJson)) {
            throw new BinaryException("未查询到国投配置，请联系管理员");
        }
        JSONObject config = JSON.parseObject(configJson);
        String assertRangeClassCodes = config.getString("assertRangeClassCodes");
        if (StringUtils.isBlank(assertRangeClassCodes)) {
            throw new BinaryException("未配置资产分类，请联系管理员");
        }
        return JSON.parseArray(assertRangeClassCodes, String.class)
                .stream().filter(Objects::nonNull).collect(Collectors.toList());
    }
}
